#ifndef ZIPHEADER_H
#define ZIPHEADER_H

#include "Types.h"

namespace Archive {
namespace Zip {

namespace Signature
{
  extern UInt32 kLocalFileHeader;
  extern UInt32 kDataDescriptor;
  extern UInt32 kCentralFileHeader;
  extern UInt32 kEndOfCentralDir;
  extern UInt32 kZip64EndOfCentralDir;
  extern UInt32 kZip64EndOfCentralDirLocator;

  static const UInt32 kMarkerSize = 4;
}

const UInt32 kEcdSize = 22;
const UInt32 kZip64EcdSize = 44;
const UInt32 kZip64EcdLocatorSize = 20;
/*
struct CEndOfCentralDirectoryRecord
{
  UInt16 ThisDiskNumber;
  UInt16 StartCentralDirectoryDiskNumber;
  UInt16 NumEntriesInCentaralDirectoryOnThisDisk;
  UInt16 NumEntriesInCentaralDirectory;
  UInt32 CentralDirectorySize;
  UInt32 CentralDirectoryStartOffset;
  UInt16 CommentSize;
};

struct CEndOfCentralDirectoryRecordFull
{
  UInt32 Signature;
  CEndOfCentralDirectoryRecord Header;
};
*/

namespace NFileHeader
{
  /*
  struct CVersion
  {
	Byte Version;
	Byte HostOS;
  };
  */

  namespace NCompressionMethod
  {
	enum EType
	{
	  kStored = 0,
	  kShrunk = 1,
	  kReduced1 = 2,
	  kReduced2 = 3,
	  kReduced3 = 4,
	  kReduced4 = 5,
	  kImploded = 6,
	  kReservedTokenizing = 7, // reserved for tokenizing
	  kDeflated = 8,
	  kDeflated64 = 9,
	  kPKImploding = 10,

	  kBZip2 = 12,
	  kLZMA = 14,
	  kTerse = 18,
	  kLz77 = 19,
	  kJpeg = 0x60,
	  kWavPack = 0x61,
	  kPPMd = 0x62,
	  kWzAES = 0x63
	};
	const int kNumCompressionMethods = 11;
	const Byte kMadeByProgramVersion = 20;

	const Byte kExtractVersion_Default = 10;
	const Byte kExtractVersion_Dir = 20;
	const Byte kExtractVersion_ZipCrypto = 20;
	const Byte kExtractVersion_Deflate = 20;
	const Byte kExtractVersion_Deflate64 = 21;
	const Byte kExtractVersion_Zip64 = 45;
	const Byte kExtractVersion_BZip2 = 46;
	const Byte kExtractVersion_Aes = 51;
	const Byte kExtractVersion_LZMA = 63;
	const Byte kExtractVersion_PPMd = 63;

	// const Byte kSupportedVersion   = 20;
  }

  namespace NExtraID
  {
	enum
	{
	  kZip64 = 0x01,
	  kNTFS = 0x0A,
	  kStrongEncrypt = 0x17,
	  kUnixTime = 0x5455,
	  kWzAES = 0x9901
	};
  }

  namespace NNtfsExtra
  {
	const UInt16 kTagTime = 1;
	enum
	{
	  kMTime = 0,
	  kATime,
	  kCTime
	};
  }

  namespace NUnixTime
  {
	enum
	{
	  kMTime = 0,
	  kATime,
	  kCTime
	};
  }

  const UInt32 kLocalBlockSize = 26;
  /*
  struct CLocalBlock
  {
	CVersion ExtractVersion;

	UInt16 Flags;
	UInt16 CompressionMethod;
	UInt32 Time;
	UInt32 FileCRC;
	UInt32 PackSize;
	UInt32 UnPackSize;
	UInt16 NameSize;
	UInt16 ExtraSize;
  };
  */

  const UInt32 kDataDescriptorSize = 16;
  // const UInt32 kDataDescriptor64Size = 16 + 8;
  /*
  struct CDataDescriptor
  {
	UInt32 Signature;
	UInt32 FileCRC;
	UInt32 PackSize;
	UInt32 UnPackSize;
  };

  struct CLocalBlockFull
  {
	UInt32 Signature;
	CLocalBlock Header;
  };
  */

  const UInt32 kCentralBlockSize = 42;
  /*
  struct CBlock
  {
	CVersion MadeByVersion;
	CVersion ExtractVersion;
	UInt16 Flags;
	UInt16 CompressionMethod;
	UInt32 Time;
	UInt32 FileCRC;
	UInt32 PackSize;
	UInt32 UnPackSize;
	UInt16 NameSize;
	UInt16 ExtraSize;
	UInt16 CommentSize;
	UInt16 DiskNumberStart;
	UInt16 InternalAttributes;
	UInt32 ExternalAttributes;
	UInt32 LocalHeaderOffset;
  };

  struct CBlockFull
  {
	UInt32 Signature;
	CBlock Header;
  };
  */

  namespace NFlags
  {
	const int kEncrypted = 1 << 0;
	const int kLzmaEOS = 1 << 1;
	const int kDescriptorUsedMask = 1 << 3;
	const int kStrongEncrypted = 1 << 6;
	const int kUtf8 = 1 << 11;

	const int kImplodeDictionarySizeMask = 1 << 1;
	const int kImplodeLiteralsOnMask     = 1 << 2;

	const int kDeflateTypeBitStart = 1;
	const int kNumDeflateTypeBits = 2;
	const int kNumDeflateTypes = (1 << kNumDeflateTypeBits);
	const int kDeflateTypeMask = (1 << kNumDeflateTypeBits) - 1;
  }

  namespace NHostOS
  {
	enum EEnum
	{
		kFAT      = 0,
		kAMIGA    = 1,
		kVMS      = 2,  // VAX/VMS
		kUnix     = 3,
		kVM_CMS   = 4,
		kAtari    = 5,  // what if it's a minix filesystem? [cjh]
		kHPFS     = 6,  // filesystem used by OS/2 (and NT 3.x)
		kMac      = 7,
		kZ_System = 8,
		kCPM      = 9,
		kTOPS20   = 10, // pkzip 2.50 NTFS
		kNTFS     = 11, // filesystem used by Windows NT
		kQDOS     = 12, // SMS/QDOS
		kAcorn    = 13, // Archimedes Acorn RISC OS
		kVFAT     = 14, // filesystem used by Windows 95, NT
		kMVS      = 15,
		kBeOS     = 16, // hybrid POSIX/database filesystem
		kTandem   = 17,
		kOS400    = 18,
		kOSX      = 19
	};
  }
  namespace NUnixAttribute
  {
	const UInt32 kIFMT   =   0170000;     /* Unix file type mask */

	const UInt32 kIFDIR  =   0040000;     /* Unix directory */
	const UInt32 kIFREG  =   0100000;     /* Unix regular file */
	const UInt32 kIFSOCK =   0140000;     /* Unix socket (BSD, not SysV or Amiga) */
	const UInt32 kIFLNK  =   0120000;     /* Unix symbolic link (not SysV, Amiga) */
	const UInt32 kIFBLK  =   0060000;     /* Unix block special       (not Amiga) */
	const UInt32 kIFCHR  =   0020000;     /* Unix character special   (not Amiga) */
	const UInt32 kIFIFO  =   0010000;     /* Unix fifo    (BCC, not MSC or Amiga) */

	const UInt32 kISUID  =   04000;       /* Unix set user id on execution */
	const UInt32 kISGID  =   02000;       /* Unix set group id on execution */
	const UInt32 kISVTX  =   01000;       /* Unix directory permissions control */
	const UInt32 kENFMT  =   kISGID;   /* Unix record locking enforcement flag */
	const UInt32 kIRWXU  =   00700;       /* Unix read, write, execute: owner */
	const UInt32 kIRUSR  =   00400;       /* Unix read permission: owner */
	const UInt32 kIWUSR  =   00200;       /* Unix write permission: owner */
	const UInt32 kIXUSR  =   00100;       /* Unix execute permission: owner */
	const UInt32 kIRWXG  =   00070;       /* Unix read, write, execute: group */
	const UInt32 kIRGRP  =   00040;       /* Unix read permission: group */
	const UInt32 kIWGRP  =   00020;       /* Unix write permission: group */
	const UInt32 kIXGRP  =   00010;       /* Unix execute permission: group */
	const UInt32 kIRWXO  =   00007;       /* Unix read, write, execute: other */
	const UInt32 kIROTH  =   00004;       /* Unix read permission: other */
	const UInt32 kIWOTH  =   00002;       /* Unix write permission: other */
	const UInt32 kIXOTH  =   00001;       /* Unix execute permission: other */
  }

  namespace NAmigaAttribute
  {
	const UInt32 kIFMT     = 06000;       /* Amiga file type mask */
	const UInt32 kIFDIR    = 04000;       /* Amiga directory */
	const UInt32 kIFREG    = 02000;       /* Amiga regular file */
	const UInt32 kIHIDDEN  = 00200;       /* to be supported in AmigaDOS 3.x */
	const UInt32 kISCRIPT  = 00100;       /* executable script (text command file) */
	const UInt32 kIPURE    = 00040;       /* allow loading into resident memory */
	const UInt32 kIARCHIVE = 00020;       /* not modified since bit was last set */
	const UInt32 kIREAD    = 00010;       /* can be opened for reading */
	const UInt32 kIWRITE   = 00004;       /* can be opened for writing */
	const UInt32 kIEXECUTE = 00002;       /* executable image, a loadable runfile */
	const UInt32 kIDELETE  = 00001;      /* can be deleted */
  }
}

}}

#endif // ZIPHEADER_H
